package graph;

import static org.junit.Assert.*;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

import org.junit.Test;

public class GraphTest {

	WeightedDirectedGraph<String, Integer>	graph;

	public void loadFromFile(String filename) {
		try {
			File file = new File(filename);
			FileReader fileReader = new FileReader(file);
			BufferedReader bufferedReader = new BufferedReader(fileReader);
			String line = bufferedReader.readLine();
			while (line != null) {
				String[] data = line.split(",");
				if (data[0].equals("vertex")) {
					graph.putVertex(data[1]);
				} else if (data[0].equals("edge")) {
					String[] data2 = data[1].split("-");
					graph.addEdge(Integer.parseInt(data2[1]), data2[0], data2[2]);
				}
				line = bufferedReader.readLine();
			}
		} catch (IOException e) {

		}
	}

	@Test
	public void testEmptyGraph() {
		graph = new WeightedDirectedGraph<String, Integer>();
		assertEquals("", graph.toString());
	}

	@Test
	public void testOneGraph() {
		testEmptyGraph();
		graph.putVertex("A");
		assertEquals("A", graph.toString());
	}

	@Test
	public void testTwoGraphLoose() {
		testOneGraph();
		graph.putVertex("B");
		assertEquals("A_B", graph.toString());
	}

	@Test
	public void testTwoGraphLinked() {
		testTwoGraphLoose();
		graph.addEdge(100, "A", "B");
		assertEquals("A[[100>B]]_B[[100>A]]", graph.toString());
	}

	@Test
	public void testThreeGraphLoose() {
		testTwoGraphLoose();
		graph.putVertex("C");
		assertEquals("A_B_C", graph.toString());
	}

	@Test
	public void testThreeGraphPartLinked() {
		testThreeGraphLoose();
		graph.addEdge(100, "A", "B");
		assertEquals("A[[100>B]]_B[[100>A]]_C", graph.toString());
	}

	@Test
	public void testThreeGraphLinked() {
		testThreeGraphPartLinked();
		graph.addEdge(100, "A", "B");
		graph.addEdge(200, "B", "C");
		graph.addEdge(300, "C", "A");
		assertEquals("A[[100>B][300>C]]_B[[100>A][200>C]]_C[[200>B][300>A]]", graph.toString());
	}

	@Test
	public void testTenGraphLoose() {
		testThreeGraphLoose();
		graph.putVertex("D");
		graph.putVertex("E");
		graph.putVertex("F");
		graph.putVertex("G");
		graph.putVertex("H");
		graph.putVertex("I");
		graph.putVertex("J");
		assertEquals("A_B_C_D_E_F_G_H_I_J", graph.toString());
	}

	@Test
	public void testTenGraphPartLinked() {
		testTenGraphLoose();
		graph.addEdge(100, "A", "B");
		graph.addEdge(200, "B", "C");
		graph.addEdge(300, "C", "D");
		assertEquals("A[[100>B]]_B[[100>A][200>C]]_C[[200>B][300>D]]_D[[300>C]]_E_F_G_H_I_J", graph.toString());
	}

	@Test
	public void testTenGraphLinked() {
		testTenGraphPartLinked();
		graph.addEdge(400, "D", "E");
		graph.addEdge(500, "E", "F");
		graph.addEdge(600, "F", "G");
		graph.addEdge(700, "G", "H");
		graph.addEdge(800, "H", "I");
		graph.addEdge(900, "I", "J");
		assertEquals("A[[100>B]]_B[[100>A][200>C]]_C[[200>B][300>D]]_D[[300>C][400>E]]_E[[400>D][500>F]]_F[[500>E][600>G]]_G[[600>F][700>H]]_H[[700>G][800>I]]_I[[800>H][900>J]]_J[[900>I]]", graph
				.toString());
	}

	@Test
	public void testHugeGraph() {
		testEmptyGraph();
		loadFromFile("hugegraph.txt");
		assertEquals(99999, graph.getSize());
	}

	@Test
	public void testEmptyGetCost() {
		testEmptyGraph();
		assertEquals(null, graph.getCost("A", "B"));
	}

	@Test
	public void testOneGraphGetCost() {
		testOneGraph();
		assertEquals(null, graph.getCost("A", "B"));
	}

	@Test
	public void testTwoGraphLooseGetCost() {
		testTwoGraphLoose();
		assertEquals(null, graph.getCost("A", "B"));
	}

	@Test
	public void testTwoGraphLinkedGetCost() {
		testTwoGraphLinked();
		assertEquals(new Integer(100), graph.getCost("A", "B"));
	}

	@Test
	public void testTwoGraphLinkedGetCost_bad() {
		testTwoGraphLinked();
		assertEquals(null, graph.getCost("A", "C"));
	}

	@Test
	public void testThreeGraphPartLinkedGetCost() {
		testThreeGraphPartLinked();
		assertEquals(new Integer(100), graph.getCost("A", "B"));
	}

	@Test
	public void testThreeGraphPartLinkedGetCost_bad() {
		testThreeGraphPartLinked();
		assertEquals(null, graph.getCost("A", "C"));
	}

	@Test
	public void testThreeGraphLinkedGetCost() {
		testThreeGraphLinked();
		assertEquals(new Integer(200), graph.getCost("B", "C"));
	}

	@Test
	public void testThreeGraphLinkedGetCost_bad() {
		testThreeGraphLinked();
		assertEquals(null, graph.getCost("Q", "V"));
	}

	@Test
	public void testTenGraphPartLinkedGetCost() {
		testTenGraphPartLinked();
		assertEquals(new Integer(200), graph.getCost("B", "C"));
	}

	@Test
	public void testTenGraphPartLinkedGetCost_bad() {
		testTenGraphPartLinked();
		assertEquals(null, graph.getCost("A", "C"));
	}

	@Test
	public void testTenGraphLinkedGetCost() {
		testTenGraphLinked();
		assertEquals(new Integer(500), graph.getCost("E", "F"));
	}

	@Test
	public void testTenGraphLinkedGetCost_bad() {
		testTenGraphLinked();
		assertEquals(null, graph.getCost("Q", "V"));
	}

	@Test
	public void testEmptyGraphDepthCount() {
		testEmptyGraph();
		assertEquals(0, graph.getDepthFirst("A").size());
	}

	@Test
	public void testEmptyGraphBreadthCount() {
		testEmptyGraph();
		assertEquals(0, graph.getBreadthFirst("A").size());
	}

	@Test
	public void testOneGraphDepthCount() {
		testOneGraph();
		assertEquals(1, graph.getDepthFirst("A").size());
	}

	@Test
	public void testOneGraphBreadthCount() {
		testOneGraph();
		assertEquals(1, graph.getBreadthFirst("A").size());
	}

	@Test
	public void testTwoGraphLooseDepthCount() {
		testTwoGraphLoose();
		assertEquals(1, graph.getDepthFirst("A").size());
	}

	@Test
	public void testTwoGraphLooseBreadthCount() {
		testTwoGraphLoose();
		assertEquals(1, graph.getBreadthFirst("A").size());
	}

	@Test
	public void testTwoGraphLinkedDepthCount() {
		testTwoGraphLinked();
		assertEquals(2, graph.getDepthFirst("A").size());
	}

	@Test
	public void testTwoGraphLinkedBreadthCount() {
		testTwoGraphLinked();
		assertEquals(2, graph.getBreadthFirst("A").size());
	}

	@Test
	public void testThreeGraphLooseDepthCount() {
		testThreeGraphLoose();
		assertEquals(1, graph.getDepthFirst("A").size());
	}

	@Test
	public void testThreeGraphLooseBreadthCount() {
		testThreeGraphLoose();
		assertEquals(1, graph.getBreadthFirst("A").size());
	}

	@Test
	public void testThreeGraphPartLinkedDepthCount() {
		testThreeGraphPartLinked();
		assertEquals(2, graph.getDepthFirst("A").size());
	}

	@Test
	public void testThreeGraphPartLinkedBreadthCount() {
		testThreeGraphPartLinked();
		assertEquals(2, graph.getBreadthFirst("A").size());
	}

	@Test
	public void testThreeGraphLinkedDepthCount() {
		testThreeGraphLinked();
		assertEquals(3, graph.getDepthFirst("A").size());
	}

	@Test
	public void testThreeGraphLinkedBreadthCount() {
		testThreeGraphLinked();
		assertEquals(3, graph.getBreadthFirst("A").size());
	}

	@Test
	public void testTenGraphPartLinkedDepthCount() {
		testTenGraphPartLinked();
		assertEquals(4, graph.getDepthFirst("B").size());
	}

	@Test
	public void testTenGraphPartLinkedBreadthCount() {
		testTenGraphPartLinked();
		assertEquals(4, graph.getBreadthFirst("B").size());
	}

	@Test
	public void testTenGraphLinkedDepthCount() {
		testTenGraphLinked();
		assertEquals(10, graph.getDepthFirst("B").size());
	}

	@Test
	public void testTenGraphLinkedBreadthCount() {
		testTenGraphLinked();
		assertEquals(10, graph.getBreadthFirst("B").size());
	}

	@Test
	public void testTenGraphLinkedDepthCount_bad() {
		testTenGraphLinked();
		assertEquals(0, graph.getDepthFirst("Q").size());
	}

	@Test
	public void testTenGraphLinkedBreadthCount_bad() {
		testTenGraphLinked();
		assertEquals(0, graph.getBreadthFirst("Q").size());
	}

}
